package mt.comm;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import java.net.Socket;
import java.net.UnknownHostException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

import mt.Order;
import mt.comm.ServerSideMessage.Type;

public class ClientCommImp implements ClientComm, Runnable {

	public final static int DEFAULT_PORT = 8080;
	Socket socket = null;
	ObjectOutputStream os = null;
	InputStream in;
	private String nickname;
	private BlockingQueue<ClienteSideMessageImp> clienteSideMessageImps = new LinkedBlockingQueue<ClienteSideMessageImp>();
	private Thread read;
	private boolean isConnected = false;

	@Override
	public void connect(String host, String nickname)
			throws UnknownHostException, IOException {
		isConnected = true;
		socket = new Socket(host, DEFAULT_PORT);
		os = new ObjectOutputStream(socket.getOutputStream());
		os.writeObject(new ServerSideMessageImp(Type.CONNECTED, nickname));
		in = socket.getInputStream();
		os.flush();
		this.nickname = nickname;
		new Thread(this).start();

	}

	@Override
	public boolean isConnected() {

		return isConnected;

	}

	@Override
	public void disconnect() {

		try {
			os.writeObject(new ServerSideMessageImp(Type.DISCONNECTED, nickname));

			socket.close();
			isConnected = false;
		} catch (IOException e) {
			// if an I/O error occurs when closing this socket
			e.printStackTrace();
		}

	}

	@Override
	public ClientSideMessage getNextMessage() {
		read = Thread.currentThread();

		try {
			return clienteSideMessageImps.take();
		} catch (InterruptedException e) {

			return null;
		}
	}

	@Override
	public boolean hasNextMessage() {

		return !clienteSideMessageImps.isEmpty();
	}

	@Override
	public void sendOrder(Order order) {
		try {
			os.writeObject(new ServerSideMessageImp(Type.NEW_ORDER, nickname,
					order));
			os.flush();
		} catch (IOException e) {
			try {
				socket.close();
			} catch (IOException e1) {
				e1.printStackTrace();
			}
		}

	}

	@Override
	public void run() {

		try {
			while (true) {
				clienteSideMessageImps
						.add((ClienteSideMessageImp) new ObjectInputStream(in)
								.readObject());

			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();

		} catch (IOException e) {
			if (read != null && !isConnected)
				read.interrupt();
			isConnected = false;
		}

	}

}
